home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / hplip / ui4 / systemtray.py < prev    next >
Encoding:
Python Source  |  2009-04-14  |  21.3 KB  |  629 lines

  1. # -*- coding: utf-8 -*-
  2. #
  3. # (c) Copyright 2003-2009 Hewlett-Packard Development Company, L.P.
  4. #
  5. # This program is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation; either version 2 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  18. #
  19. # Author: Don Welch
  20.  
  21. # Std Lib
  22. import sys
  23. import struct
  24. import select
  25. import os
  26. import signal
  27. import os.path
  28. import time
  29.  
  30.  
  31. # Local
  32. from base.g import *
  33. from base import device, utils, models
  34. from base.codes import *
  35. from ui_utils import *
  36.  
  37. # PyQt
  38. try:
  39.     from PyQt4.QtCore import *
  40.     from PyQt4.QtGui import *
  41. except ImportError:
  42.     log.error("Python bindings for Qt4 not found. Try using --qt3. Exiting!")
  43.     sys.exit(1)
  44.  
  45. from systrayframe import SystrayFrame
  46.  
  47. # dbus
  48. try:
  49.     import dbus
  50.     #import dbus.service
  51.     from dbus import SessionBus, lowlevel
  52.     #from dbus.mainloop.qt import DBusQtMainLoop
  53. except ImportError:
  54.     log.error("Python bindings for dbus not found. Exiting!")
  55.     sys.exit(1)
  56.  
  57.  
  58.  
  59.  
  60. TRAY_MESSAGE_DELAY = 10000
  61. HIDE_INACTIVE_DELAY = 5000
  62. BLIP_DELAY = 2000
  63. SET_MENU_DELAY = 1000
  64. MAX_MENU_EVENTS = 10
  65.  
  66. ERROR_STATE_TO_ICON = {
  67.     ERROR_STATE_CLEAR: QSystemTrayIcon.Information,
  68.     ERROR_STATE_OK: QSystemTrayIcon.Information,
  69.     ERROR_STATE_WARNING: QSystemTrayIcon.Warning,
  70.     ERROR_STATE_ERROR: QSystemTrayIcon.Critical,
  71.     ERROR_STATE_LOW_SUPPLIES: QSystemTrayIcon.Warning,
  72.     ERROR_STATE_BUSY: QSystemTrayIcon.Warning,
  73.     ERROR_STATE_LOW_PAPER: QSystemTrayIcon.Warning,
  74.     ERROR_STATE_PRINTING: QSystemTrayIcon.Information,
  75.     ERROR_STATE_SCANNING: QSystemTrayIcon.Information,
  76.     ERROR_STATE_PHOTOCARD: QSystemTrayIcon.Information,
  77.     ERROR_STATE_FAXING: QSystemTrayIcon.Information,
  78.     ERROR_STATE_COPYING: QSystemTrayIcon.Information,
  79. }
  80.  
  81. devices = {} # { <device_uri> : HistoryDevice(), ... }
  82.  
  83.  
  84. class DeviceMenu(QMenu):
  85.     def __init__(self, title, parent, device_uri, device_hist, index):
  86.         QMenu.__init__(self, title, parent)
  87.         self.device_uri = device_uri
  88.         self.device_hist = device_hist
  89.         self.index = index
  90.  
  91.  
  92.     def update(self):
  93.         self.clear()
  94.  
  95.         if self.device_hist:
  96.             first = True
  97.             for e in self.device_hist:
  98.                 error_state = STATUS_TO_ERROR_STATE_MAP.get(e.event_code, ERROR_STATE_CLEAR)
  99.                 ess = device.queryString(e.event_code, 0)
  100.  
  101.                 a = QAction(QIcon(getStatusListIcon(error_state)[self.index]),
  102.                                     QString("%1 %2").arg(ess).arg(getTimeDeltaDesc(e.timedate)), self)
  103.  
  104.                 if first:
  105.                     f = a.font()
  106.                     f.setBold(True)
  107.                     a.setFont(f)
  108.                     self.setIcon(QIcon(getStatusListIcon(error_state)[self.index]))
  109.                     first = False
  110.  
  111.                 self.addAction(a)
  112.  
  113.         else:
  114.             self.addAction(QIcon(load_pixmap("warning", "16x16")),
  115.                 QApplication.translate("SystemTray", "(No events)", None, QApplication.UnicodeUTF8))
  116.  
  117.  
  118.  
  119. class HistoryDevice(QObject):
  120.     def __init__(self, device_uri, needs_update=True):
  121.         self.needs_update = needs_update
  122.         self.device_uri = device_uri
  123.  
  124.         back_end, is_hp, bus, model, serial, dev_file, host, port = \
  125.                 device.parseDeviceURI(device_uri)
  126.  
  127.         if bus == 'usb':
  128.             self.id = serial
  129.         elif bus == 'net':
  130.             self.id = host
  131.         elif bus == 'par':
  132.             self.id = dev_file
  133.         else:
  134.             self.id = 'unknown'
  135.  
  136.         self.model = models.normalizeModelUIName(model)
  137.  
  138.         if back_end == 'hp':
  139.             self.device_type = DEVICE_TYPE_PRINTER
  140.             self.menu_text = self.__tr("%1 Printer (%2)").arg(self.model).arg(self.id)
  141.  
  142.         elif back_end == 'hpaio':
  143.             self.device_type = DEVICE_TYPE_SCANNER
  144.             self.menu_text = self.__tr("%1 Scanner (%2)").arg(self.model).arg(self.id)
  145.  
  146.         elif back_end == 'hpfax':
  147.             self.device_type = DEVICE_TYPE_FAX
  148.             self.menu_text = self.__tr("%1 Fax (%2)").arg(self.model).arg(self.id)
  149.  
  150.         else:
  151.             self.device_type = DEVICE_TYPE_UNKNOWN
  152.             self.menu_text = self.__tr("%1 (%2)").arg(self.model).arg(self.id)
  153.  
  154.         self.mq = device.queryModelByURI(self.device_uri)
  155.         self.index = 0
  156.         if self.mq.get('tech-type', TECH_TYPE_NONE) in (TECH_TYPE_MONO_LASER, TECH_TYPE_COLOR_LASER):
  157.             self.index = 1
  158.         self.history = None
  159.  
  160.  
  161.     def getHistory(self, service):
  162.         if service is not None and self.needs_update:
  163.             device_uri, h = service.GetHistory(self.device_uri)
  164.             self.history = [device.Event(*tuple(e)) for e in list(h)[:-MAX_MENU_EVENTS:-1]]
  165.             self.needs_update = False
  166.  
  167.  
  168.     def __tr(self, s, c=None):
  169.         return QApplication.translate("SystemTray", s, c, QApplication.UnicodeUTF8)
  170.  
  171.  
  172.  
  173.  
  174. class SystraySettingsDialog(QDialog):
  175.     def __init__(self, parent, systray_visible, polling,
  176.                  polling_interval, device_list=None):
  177.  
  178.         QDialog.__init__(self, parent)
  179.  
  180.         self.systray_visible = systray_visible
  181.  
  182.         if device_list is not None:
  183.             self.device_list = device_list
  184.         else:
  185.             self.device_list = {}
  186.  
  187.         self.polling = polling
  188.         self.polling_interval = polling_interval
  189.  
  190.         self.initUi()
  191.         self.SystemTraySettings.updateUi()
  192.  
  193.  
  194.     def initUi(self):
  195.         self.setObjectName("SystraySettingsDialog")
  196.         self.resize(QSize(QRect(0,0,488,565).size()).expandedTo(self.minimumSizeHint()))
  197.  
  198.         self.gridlayout = QGridLayout(self)
  199.         self.gridlayout.setObjectName("gridlayout")
  200.  
  201.         self.SystemTraySettings = SystrayFrame(self)
  202.         self.SystemTraySettings.initUi(self.systray_visible,
  203.                                        self.polling, self.polling_interval,
  204.                                        self.device_list)
  205.  
  206.         sizePolicy = QSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding)
  207.         sizePolicy.setHorizontalStretch(0)
  208.         sizePolicy.setVerticalStretch(0)
  209.         sizePolicy.setHeightForWidth(self.SystemTraySettings.sizePolicy().hasHeightForWidth())
  210.         self.SystemTraySettings.setSizePolicy(sizePolicy)
  211.         self.SystemTraySettings.setFrameShadow(QFrame.Raised)
  212.         self.SystemTraySettings.setObjectName("SystemTraySettings")
  213.         self.gridlayout.addWidget(self.SystemTraySettings,0,0,1,2)
  214.  
  215.         spacerItem = QSpacerItem(301,20,QSizePolicy.Expanding,QSizePolicy.Minimum)
  216.         self.gridlayout.addItem(spacerItem,1,0,1,1)
  217.  
  218.         self.StdButtons = QDialogButtonBox(self)
  219.         self.StdButtons.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.NoButton|QDialogButtonBox.Ok)
  220.         self.StdButtons.setCenterButtons(False)
  221.         self.StdButtons.setObjectName("StdButtons")
  222.         self.gridlayout.addWidget(self.StdButtons,1,1,1,1)
  223.  
  224.         QObject.connect(self.StdButtons, SIGNAL("accepted()"), self.acceptClicked)
  225.         QObject.connect(self.StdButtons, SIGNAL("rejected()"), self.reject)
  226.         #QMetaObject.connectSlotsByName(self)
  227.  
  228.         self.setWindowTitle(self.__tr("HP Device Manager - System Tray Settings"))
  229.  
  230.  
  231.     def acceptClicked(self):
  232.         self.systray_visible = self.SystemTraySettings.systray_visible
  233.         self.polling = self.SystemTraySettings.polling
  234.         self.polling_interval = self.SystemTraySettings.polling_interval
  235.         self.device_list = self.SystemTraySettings.device_list
  236.         self.accept()
  237.  
  238.  
  239.     def __tr(self, s, c=None):
  240.         return QApplication.translate("SystraySettingsDialog", s, c, QApplication.UnicodeUTF8)
  241.  
  242.  
  243.  
  244. class SystemTrayApp(QApplication):
  245.     def __init__(self, args, read_pipe):
  246.         QApplication.__init__(self, args)
  247.  
  248.         self.menu = None
  249.         self.read_pipe = read_pipe
  250.         self.fmt = "64s64sI32sI64sf"
  251.         self.fmt_size = struct.calcsize(self.fmt)
  252.         self.timer_active = False
  253.         self.active_icon = False
  254.         self.user_settings = UserSettings()
  255.         self.user_settings.load()
  256.  
  257.         self.tray_icon = QSystemTrayIcon()
  258.  
  259.         pm = load_pixmap("prog", "48x48") #, (22, 22))
  260.         self.prop_icon = QIcon(pm)
  261.  
  262.         a = load_pixmap('active', '16x16')
  263.         painter = QPainter(pm)
  264.         painter.drawPixmap(32, 0, a)
  265.         painter.end()
  266.  
  267.         self.prop_active_icon = QIcon(pm)
  268.  
  269.         self.tray_icon.setIcon(self.prop_icon)
  270.  
  271.         self.session_bus = SessionBus()
  272.         self.service = None
  273.  
  274.         for d in device.getSupportedCUPSDevices(back_end_filter=['hp', 'hpfax']):
  275.             self.addDevice(d)
  276.  
  277.         self.tray_icon.setToolTip(self.__tr("HPLIP Status Service"))
  278.  
  279.         QObject.connect(self.tray_icon, SIGNAL("messageClicked()"), self.messageClicked)
  280.  
  281.         notifier = QSocketNotifier(self.read_pipe, QSocketNotifier.Read)
  282.         QObject.connect(notifier, SIGNAL("activated(int)"), self.notifierActivated)
  283.  
  284.         QObject.connect(self.tray_icon, SIGNAL("activated(QSystemTrayIcon::ActivationReason)"), self.trayActivated)
  285.  
  286.         self.tray_icon.show()
  287.  
  288.         if self.user_settings.systray_visible == SYSTRAY_VISIBLE_SHOW_ALWAYS:
  289.             self.tray_icon.setVisible(True)
  290.         else:
  291.             QTimer.singleShot(HIDE_INACTIVE_DELAY, self.timeoutHideWhenInactive) # show icon for awhile @ startup
  292.  
  293.         self.tray_icon.setIcon(self.prop_active_icon)
  294.         self.active_icon = True
  295.  
  296.         QTimer.singleShot(SET_MENU_DELAY, self.initDone)
  297.  
  298.  
  299.     def initDone(self):
  300.         self.tray_icon.setIcon(self.prop_icon)
  301.         self.active_icon = False
  302.  
  303.         self.setMenu()
  304.  
  305.  
  306.     def addDevice(self, device_uri):
  307.         try:
  308.             devices[device_uri]
  309.         except KeyError:
  310.             devices[device_uri] = HistoryDevice(device_uri)
  311.         else:
  312.             devices[device_uri].needs_update = True
  313.  
  314.  
  315.  
  316.     def setMenu(self):
  317.         self.menu = QMenu()
  318.  
  319.         title = QWidgetAction(self.menu)
  320.         #title.setDisabled(True)
  321.  
  322.         hbox = QFrame(self.menu)
  323.         layout = QHBoxLayout(hbox)
  324.         layout.setMargin(3)
  325.         layout.setSpacing(5)
  326.         pix_label = QLabel(hbox)
  327.  
  328.         layout.insertWidget(-1, pix_label, 0)
  329.  
  330.         icon_size = self.menu.style().pixelMetric(QStyle.PM_SmallIconSize)
  331.         pix_label.setPixmap(self.prop_icon.pixmap(icon_size))
  332.  
  333.         label = QLabel(hbox)
  334.         layout.insertWidget(-1, label, 20)
  335.         title.setDefaultWidget(hbox)
  336.  
  337.         label.setText(self.__tr("HPLIP Status Service"))
  338.  
  339.         f = label.font()
  340.         f.setBold(True)
  341.         label.setFont(f)
  342.         self.menu.insertAction(None, title)
  343.  
  344.         if devices:
  345.             if self.service is None:
  346.                 t = 0
  347.                 while t < 3:
  348.                     try:
  349.                         self.service = self.session_bus.get_object('com.hplip.StatusService',
  350.                                                                   "/com/hplip/StatusService")
  351.                     except DBusException:
  352.                         log.warn("Unable to connect to StatusService. Retrying...")
  353.  
  354.                     t += 1
  355.                     time.sleep(0.5)
  356.  
  357.             if self.service is not None:
  358.                 self.menu.addSeparator()
  359.  
  360.                 for d in devices:
  361.                     devices[d].getHistory(self.service)
  362.  
  363.                     menu = DeviceMenu(devices[d].menu_text, self.menu, d, devices[d].history, devices[d].index)
  364.                     self.menu.addMenu(menu)
  365.                     menu.update()
  366.  
  367.  
  368.         self.menu.addSeparator()
  369.         self.menu.addAction(self.__tr("HP Device Manager..."), self.toolboxTriggered)
  370.  
  371.         self.menu.addSeparator()
  372.  
  373.         self.settings_action = self.menu.addAction(QIcon(load_pixmap('settings', '16x16')),
  374.                                     self.__tr("Settings..."),  self.settingsTriggered)
  375.  
  376.         self.menu.addSeparator()
  377.         self.menu.addAction(QIcon(load_pixmap('quit', '16x16')), "Quit", self.quitTriggered)
  378.         self.tray_icon.setContextMenu(self.menu)
  379.  
  380.  
  381.  
  382.  
  383.     def settingsTriggered(self):
  384.         if self.menu is None:
  385.             return
  386.  
  387.         self.sendMessage('', '', EVENT_DEVICE_STOP_POLLING)
  388.         try:
  389.             dlg = SystraySettingsDialog(self.menu, self.user_settings.systray_visible,
  390.                                         self.user_settings.polling, self.user_settings.polling_interval,
  391.                                         self.user_settings.polling_device_list)
  392.  
  393.             if dlg.exec_() == QDialog.Accepted:
  394.                 self.user_settings.systray_visible = dlg.systray_visible
  395.  
  396.                 self.user_settings.save()
  397.  
  398.                 if self.user_settings.systray_visible == SYSTRAY_VISIBLE_SHOW_ALWAYS:
  399.                     log.debug("Showing...")
  400.                     self.tray_icon.setVisible(True)
  401.  
  402.                 else:
  403.                     log.debug("Waiting to hide...")
  404.                     QTimer.singleShot(HIDE_INACTIVE_DELAY, self.timeoutHideWhenInactive)
  405.  
  406.                 self.sendMessage('', '', EVENT_USER_CONFIGURATION_CHANGED)
  407.  
  408.         finally:
  409.             self.sendMessage('', '', EVENT_DEVICE_START_POLLING)
  410.  
  411.  
  412.     def timeoutHideWhenInactive(self):
  413.         log.debug("Hiding...")
  414.         if self.user_settings.systray_visible in (SYSTRAY_VISIBLE_HIDE_WHEN_INACTIVE, SYSTRAY_VISIBLE_HIDE_ALWAYS):
  415.             self.tray_icon.setVisible(False)
  416.             log.debug("Hidden")
  417.  
  418.  
  419.     def updateMenu(self):
  420.         if self.menu is None:
  421.             return
  422.         for a in self.menu.actions():
  423.             try:
  424.                 a.menu().update()
  425.             except AttributeError:
  426.                 continue
  427.  
  428.  
  429.  
  430.     def trayActivated(self, reason):
  431.         if reason == QSystemTrayIcon.Context:
  432.             self.updateMenu()
  433.  
  434.  
  435.         elif reason == QSystemTrayIcon.DoubleClick:
  436.             #print "double click"
  437.             self.toolboxTriggered()
  438.             pass
  439.  
  440.         elif reason == QSystemTrayIcon.Trigger:
  441.             #print "single click"
  442.             pass
  443.  
  444.         elif reason == QSystemTrayIcon.MiddleClick:
  445.             #print "middle click"
  446.             pass
  447.  
  448.  
  449.     def messageClicked(self):
  450.         #print "\nPARENT: message clicked"
  451.         pass
  452.  
  453.  
  454.     def quitTriggered(self):
  455.         log.debug("Exiting")
  456.         self.sendMessage('', '', EVENT_SYSTEMTRAY_EXIT)
  457.         self.quit()
  458.  
  459.  
  460.     def toolboxTriggered(self):
  461.         try:
  462.             os.waitpid(-1, os.WNOHANG)
  463.         except OSError:
  464.             pass
  465.  
  466.         # See if it is already running...
  467.         ok, lock_file = utils.lock_app('hp-toolbox', True)
  468.  
  469.         if ok: # able to lock, not running...
  470.             utils.unlock(lock_file)
  471.  
  472.             path = utils.which('hp-toolbox')
  473.             if path:
  474.                 path = os.path.join(path, 'hp-toolbox')
  475.             else:
  476.                 self.tray_icon.showMessage(self.__tr("HPLIP Status Service"),
  477.                                 self.__tr("Unable to locate hp-toolbox on system PATH."),
  478.                                 QSystemTrayIcon.Critical, TRAY_MESSAGE_DELAY)
  479.  
  480.                 log.error("Unable to find hp-toolbox on PATH.")
  481.                 return
  482.  
  483.             #log.debug(path)
  484.             log.debug("Running hp-toolbox: hp-toolbox")
  485.             os.spawnlp(os.P_NOWAIT, path, 'hp-toolbox')
  486.  
  487.         else: # ...already running, raise it
  488.             self.sendMessage('', '', EVENT_RAISE_DEVICE_MANAGER, interface='com.hplip.Toolbox')
  489.  
  490.  
  491.     def sendMessage(self, device_uri, printer_name, event_code, username=prop.username,
  492.                     job_id=0, title='', pipe_name='', interface='com.hplip.StatusService'):
  493.         #device.Event(device_uri, printer_name, event_code, username, job_id, title).send_via_dbus(SessionBus(), interface)
  494.         device.Event(device_uri, printer_name, event_code, username, job_id, title).send_via_dbus(self.session_bus, interface)
  495.  
  496.  
  497.     def notifierActivated(self, s):
  498.         m = ''
  499.         while True:
  500.             try:
  501.                 r, w, e = select.select([self.read_pipe], [], [self.read_pipe], 1.0)
  502.             except select.error:
  503.                 log.debug("Error in select()")
  504.                 break
  505.  
  506.             if e:
  507.                 log.error("Pipe error: %s" % e)
  508.                 break
  509.  
  510.             if r:
  511.                 m = ''.join([m, os.read(self.read_pipe, self.fmt_size)])
  512.                 while len(m) >= self.fmt_size:
  513.                     event = device.Event(*struct.unpack(self.fmt, m[:self.fmt_size]))
  514.  
  515.                     m = m[self.fmt_size:]
  516.  
  517.                     if event.event_code == EVENT_USER_CONFIGURATION_CHANGED:
  518.                         log.debug("Re-reading configuration (EVENT_USER_CONFIGURATION_CHANGED)")
  519.                         self.user_settings.load()
  520.                         self.user_settings.debug()
  521.  
  522.                     elif event.event_code == EVENT_SYSTEMTRAY_EXIT:
  523.                         self.quit()
  524.                         return
  525.  
  526.                     if self.user_settings.systray_visible in \
  527.                         (SYSTRAY_VISIBLE_SHOW_ALWAYS, SYSTRAY_VISIBLE_HIDE_WHEN_INACTIVE):
  528.  
  529.                         log.debug("Showing...")
  530.                         self.tray_icon.setVisible(True)
  531.  
  532.                         if event.event_code == EVENT_DEVICE_UPDATE_ACTIVE:
  533.                             if not self.active_icon:
  534.                                 self.tray_icon.setIcon(self.prop_active_icon)
  535.                                 self.active_icon = True
  536.                             continue
  537.  
  538.                         elif event.event_code == EVENT_DEVICE_UPDATE_INACTIVE:
  539.                             if self.active_icon:
  540.                                 self.tray_icon.setIcon(self.prop_icon)
  541.                                 self.active_icon = False
  542.                             continue
  543.  
  544.                         elif event.event_code == EVENT_DEVICE_UPDATE_BLIP:
  545.                             if not self.active_icon:
  546.                                 self.tray_icon.setIcon(self.prop_active_icon)
  547.                                 self.active_icon = True
  548.                                 QTimer.singleShot(BLIP_DELAY, self.blipTimeout)
  549.                             continue
  550.  
  551.                     if self.user_settings.systray_visible in (SYSTRAY_VISIBLE_HIDE_WHEN_INACTIVE, SYSTRAY_VISIBLE_HIDE_ALWAYS):
  552.                         log.debug("Waiting to hide...")
  553.                         QTimer.singleShot(HIDE_INACTIVE_DELAY, self.timeoutHideWhenInactive)
  554.  
  555.                     if event.event_code <= EVENT_MAX_USER_EVENT:
  556.                         self.addDevice(event.device_uri)
  557.                         self.setMenu()
  558.  
  559.                         if self.tray_icon.supportsMessages():
  560.  
  561.                             log.debug("Tray icon message:")
  562.                             event.debug()
  563.  
  564.                             error_state = STATUS_TO_ERROR_STATE_MAP.get(event.event_code, ERROR_STATE_CLEAR)
  565.                             icon = ERROR_STATE_TO_ICON.get(error_state, QSystemTrayIcon.Information)
  566.                             desc = device.queryString(event.event_code)
  567.  
  568.                             if event.job_id and event.title:
  569.                                 log.debug("Bubble: uri=%s desc=%s title=%s user=%s job_id=%d code=%d" %
  570.                                           (event.device_uri, desc, event.title, event.username, event.job_id, event.event_code))
  571.                                 self.tray_icon.showMessage(self.__tr("HPLIP Device Status"),
  572.                                     QString("%1\n%2: %3\n(%4/%5)").\
  573.                                     arg(event.device_uri).\
  574.                                     arg(desc).arg(event.title).\
  575.                                     arg(event.username).arg(event.job_id),
  576.                                     icon, TRAY_MESSAGE_DELAY)
  577.  
  578.                             else:
  579.                                 log.debug("Bubble: uri=%s desc=%s code=%d" % (event.device_uri, desc, event.event_code))
  580.                                 self.tray_icon.showMessage(self.__tr("HPLIP Device Status"),
  581.                                     QString("%1\n%2 (%3)").arg(event.device_uri).\
  582.                                     arg(desc).arg(event.event_code),
  583.                                     icon, TRAY_MESSAGE_DELAY)
  584.  
  585.             else:
  586.                 break
  587.  
  588.  
  589.     def blipTimeout(self):
  590.         if self.active_icon:
  591.             self.tray_icon.setIcon(self.prop_icon)
  592.             self.active_icon = False
  593.  
  594.  
  595.  
  596.     def __tr(self, s, c=None):
  597.         return QApplication.translate("SystemTray", s, c, QApplication.UnicodeUTF8)
  598.  
  599.  
  600.  
  601. def run(read_pipe):
  602.     log.set_module("hp-systray(qt4)")
  603.     log.debug("PID=%d" % os.getpid())
  604.  
  605.     app = SystemTrayApp(sys.argv, read_pipe)
  606.     app.setQuitOnLastWindowClosed(False) # If not set, settings dlg closes app
  607.  
  608.     i = 0
  609.     while i < 10:
  610.         if QSystemTrayIcon.isSystemTrayAvailable():
  611.             break
  612.         time.sleep(1.0)
  613.         i += 1
  614.  
  615.     if not QSystemTrayIcon.isSystemTrayAvailable():
  616.         FailureUI(None,
  617.             QApplication.translate("SystemTray",
  618.             "<b>No system tray detected on this system.</b><p>Unable to start, exiting.</p>",
  619.             None, QApplication.UnicodeUTF8),
  620.             QApplication.translate("SystemTray", "HPLIP Status Service",
  621.             None, QApplication.UnicodeUTF8))
  622.     else:
  623.         notifier = QSocketNotifier(read_pipe, QSocketNotifier.Read)
  624.         QObject.connect(notifier, SIGNAL("activated(int)"), app.notifierActivated)
  625.  
  626.         app.exec_()
  627.  
  628.  
  629.